package cn.com.bluemoon.daps.sync.feignclient;

import cn.com.bluemoon.daps.api.sys.RemoteSysConfigService;
import cn.com.bluemoon.daps.api.sys.RemoteSystemDatasourceService;
import cn.com.bluemoon.daps.api.sys.RemoteSystemInfoService;
import cn.com.bluemoon.daps.api.sys.RemoteSystemUserService;
import cn.com.bluemoon.daps.common.domain.ResultBean;
import cn.com.bluemoon.daps.common.enums.SyncToEnv;
import cn.com.bluemoon.daps.common.exception.DapException;
import cn.com.bluemoon.daps.common.exception.DapThrowException;
import cn.com.bluemoon.daps.common.toolkit.BmAssetUtils;
import cn.com.bluemoon.daps.sync.core.sync.GlobalConfig;
import cn.com.bluemoon.daps.system.dto.DatasourceDto;
import cn.com.bluemoon.daps.system.dto.SystemUserDto;
import cn.com.bluemoon.daps.system.entity.DapSystemConfigSandbox;
import cn.com.bluemoon.daps.system.entity.DapSystemDatasource;
import cn.com.bluemoon.daps.system.entity.DapSystemDatasourceEnvironment;
import cn.com.bluemoon.daps.system.entity.DapSystemInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 调用系统模块接口的门面
 */
@Service
@Slf4j
public class DapSystemModuleFacade {
    @Autowired
    private RemoteSystemInfoService remoteSystemInfoService;
    @Autowired
    private RemoteSystemDatasourceService remoteSystemDatasourceService;
    @Autowired
    private RemoteSystemUserService remoteSystemUserService;
    @Autowired
    private RemoteSysConfigService remoteSysConfigService;

    /**
     * 获取数据源
     *
     * @param dataSourceId 数据源id
     * @return
     */
    public DapSystemDatasource getDbTypeByDataSourceId(String dataSourceId) {
        Optional<DapSystemDatasource> datasourceOpt = Optional.ofNullable(remoteSystemDatasourceService.getById(dataSourceId));
        DapSystemDatasource datasource = datasourceOpt.orElseThrow(() -> new DapException("获取系统数据源失败！！"));
        return datasource;
    }

    /**
     * 获取系统信息
     *
     * @param systemId 系统id
     * @return 获取系统信息
     */
    public Optional<DapSystemInfo> getSystemInfo(String systemId) {
        ResultBean<DapSystemInfo> systemInfoR = remoteSystemInfoService.getSystemInfo(systemId);
        DapSystemInfo systemInfo = systemInfoR.getContent();
        return Optional.ofNullable(systemInfo);
    }

    /**
     * id获取数据源
     *
     * @param dataSourceId id
     * @return id获取数据源
     */
    public Optional<DapSystemDatasource> getSysDataSourceById(String dataSourceId) {
        ResultBean<DapSystemDatasource> datasource = remoteSystemDatasourceService.getDatasource(dataSourceId);
        return Optional.ofNullable(datasource.getContent());
    }

    /**
     * 获取系统DBA用户信息
     *
     * @return x
     */
    public List<SystemUserDto> getSysDbaRoleUser() {
        return remoteSystemUserService.userDba().getContent();
    }

    private List<SystemUserDto> findAllSystemUser() {
        ResultBean<List<SystemUserDto>> list = remoteSystemUserService.list();
        if (list == null || list.getContent() == null) {
            return Collections.emptyList();
        }
        return list.getContent();
    }

    /**
     * 根据用户账号获取系统用户名
     *
     * @param accounts acc
     * @return username
     */
    public List<String> systemUserNames(List<String> accounts) {
        Map<String, SystemUserDto> accountAndPos = findAllSystemUser().stream().collect(Collectors.toMap(SystemUserDto::getAccount, a -> a, (a, b) -> a));
        return accounts.stream().map(a -> {
            SystemUserDto userDto = accountAndPos.getOrDefault(a, null);
            return userDto == null ? a : userDto.getUserName();
        }).collect(Collectors.toList());
    }

    /**
     * 根据用户账号获取系统用户名
     *
     * @param account acc
     * @return username
     */
    public String systemUserName(String account) {
        return systemUserNames(Collections.singletonList(account)).get(0);
    }
    /**
     * 获取系统最新沙箱环境+无则报错
     *
     * @return 获取系统沙箱环境+无则报错
     */
    public DapSystemConfigSandbox getNewestSandboxConfig() {
        ResultBean<DapSystemConfigSandbox> resR = remoteSysConfigService.sandboxConfig();
        DapSystemConfigSandbox sandbox = resR.assetTrue();
        return sandbox;
    }

    /**
     * 获取数据源+环境信息+全环境信息
     *
     * @param dataSourceId 数据源id
     * @param syncToEnv    期望环境
     * @return DataSourceAndEnv
     */
    public GlobalConfig.DataSourceAndEnv getSysDataSourceAndEnvByIdAndEnv(String dataSourceId, SyncToEnv syncToEnv) {
        ResultBean<DatasourceDto> dsR = remoteSystemDatasourceService.getDatasourceInfo(dataSourceId);
        BmAssetUtils.isTrue(dsR.isOk(), dsR.getMsg());
        DatasourceDto ds = dsR.getContent();
        BmAssetUtils.notNull(ds.getDapSystemDatasource(), "获取数据源为空！");
        Optional<DapSystemDatasourceEnvironment> dsEnv = ds.getList().stream().filter(d -> {
            if (SyncToEnv.MODEL.equals(syncToEnv) || SyncToEnv.NONE.equals(syncToEnv)) {
                log.warn("同步到模型或者申请发布（获取模型版本数据），获取开发库的数据源");
                return SyncToEnv.DEV.equals(SyncToEnv.valOf(d.getEnvironment()));
            }
            return syncToEnv.equals(SyncToEnv.valOf(d.getEnvironment()));
        }).findFirst();
        // 若为None则不提供环境连接信息 eg:申请发布中无需拉取环境信息
        DapSystemDatasourceEnvironment env = SyncToEnv.NONE.equals(syncToEnv) ? dsEnv.orElse(null) :
                dsEnv.orElseThrow(() -> {
                    SyncToEnv sEnv = syncToEnv;
                    if (SyncToEnv.MODEL.equals(syncToEnv)) {
                        sEnv = SyncToEnv.DEV;
                    }
                    return new DapThrowException("模型所属数据源环境[" + sEnv.getDesc() + "]不存在，不可同步");
                });
        // 2021/6/25 增加沙箱环境连接信息 目前维护在一个 dap_system_config_sandbox
        DapSystemConfigSandbox sandbox = getNewestSandboxConfig();
        return GlobalConfig.DataSourceAndEnv.builder().ds(ds.getDapSystemDatasource()).env(env)
                .sandboxEnv(sandbox).allEnv(ds.getList()).build();
    }

}
